﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MathematicallySafe.HeadCounter.Data;
using MathematicallySafe.HeadCounter.Data.Common;
using MathematicallySafe.HeadCounter.Data.Models;
using StructureMap;

namespace MathematicallySafe.HeadCounter.Services.Forums
{
    public class ForumRaidPost
    {
        private static readonly IHeadCounterService HeadCounterService = ObjectFactory.GetInstance<IHeadCounterService>();
        private static readonly Options Options = ObjectFactory.GetInstance<IHeadCounterService>().Options;
        private static readonly Guild Guild = ObjectFactory.GetInstance<IHeadCounterService>().Guild;

        private readonly IForumFormatter format;

        private string _post;
        private Raid _raid;

        public ForumRaidPost(IForumFormatter format)
        {
            this.format = format;
        }

        public string Generate(Raid raid)
        {
            _raid = raid;
            _post = "";

            PostRaidDetails();
            _post += Environment.NewLine;
            PostAttendance();
            _post += Environment.NewLine;
            PostLoot();
            _post += Environment.NewLine;

            return _post;
        }

        private void PostRaidDetails()
        {
            _post += format.EpicTitle(_raid.Zone) + Environment.NewLine;
            _post += format.SubTitle(_raid.Date.ToString("dddd, MMM d yyyy")) + Environment.NewLine;

            PostBossKills();
        }

        private void PostBossKills()
        {
            // todo _raid.BossKills is alwyas missing but should be coming from HeadCount.
            var bosses = _raid.Loot.Where(l => !l.Boss.Contains("Trash")).Select(l => l.Boss).Distinct();
            if (bosses.Count() > 0)
            {
                var bossList = "";
                bosses.ForEach(b => bossList += b + ", ");
                _post += bossList.Substring(0, bossList.Length - 2) + Environment.NewLine;
            }
        }

        private void PostAttendance()
        {
            _post += format.SubHeading("Attendance") + Environment.NewLine;

            var attendees = from a in _raid.Attendees
                            where a.Minutes >= 30
                            join r in HeadCounterService.Guild.Raiders on a.RaiderIdentity equals r.Identity
                            orderby r.Class, r.WebSafeName
                            select r;

            int n = attendees.Count();
            PostAttendeeList(attendees.Take(10));
            if (n > 10) PostAttendeeList(attendees.Skip(10).Take(10));
            if (n > 20) PostAttendeeList(attendees.Skip(20));
            
            _post += Environment.NewLine;

            var raidLoggedExtraAttendees = from a in _raid.Attendees
                            where a.Minutes < 30
                            join r in HeadCounterService.Guild.Raiders on a.RaiderIdentity equals r.Identity
                            orderby r.Class, r.WebSafeName
                            select r;

            var extraAttendees = from a in _raid.ExtraAttendees
                                 join r in HeadCounterService.Guild.Raiders on a equals r.MainName
                                 select r;

            var allExtra = raidLoggedExtraAttendees.Union(extraAttendees).OrderBy(r => r.Class).ThenBy(r => r.WebSafeName);

            n = allExtra.Count();
            if (n > 0)
            {
                _post += format.SubHeading("Attendance Credit") + Environment.NewLine;
                PostAttendeeList(allExtra);
                _post += Environment.NewLine;
            }
        }

        private void PostAttendeeList(IEnumerable<Raider> attendees)
        {
            var players = "";
            attendees.ForEach(raider => players += format.Colour(format.Bold(raider.WebSafeName), raider.Class.ClassContrastColourString()) + ", ");
            _post += players.Substring(0, players.Length - 2) + Environment.NewLine;
        }

        private void PostLoot()
        {
            _post += format.SubHeading("Loot") + Environment.NewLine;

            // todo remove null check which is just to prevent acidic blood related problem
            var loot = from l in _raid.Loot
                       where l.Outcome == LootOutcome.Won && l.Item != null
                       select l;

            PostLootList(loot);


        }

        private void PostLootList(IEnumerable<RaidLoot> loot)
        {
            var lootList = "";
            loot.ForEach(l =>
                             {
                                 var winner = Guild.Raiders.First(r => r.Identity == l.WinnerIdentity);

                                 lootList += format.Bold(winner.WebSafeName) + " - " +
                                     format.ItemLink(l.ItemName, l.Item.LootUri.ToString()) + Environment.NewLine;
//                                 lootList +=
//                                     format.Colour(format.Bold(winner.WebSafeName),
//                                                   winner.Class.ClassContrastColourString()) + " - " +
//                                     format.ItemLink(l.ItemName, l.Item.LootUri.ToString()) + Environment.NewLine;
                             });

            _post += lootList;
        }

    }
}
